exceptions.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. import typing as t
  2. if t.TYPE_CHECKING:
  3. from .runtime import Undefined
  4. class TemplateError(Exception):
  5. """Baseclass for all template errors."""
  6. def __init__(self, message: t.Optional[str] = None) -> None:
  7. super().__init__(message)
  8. @property
  9. def message(self) -> t.Optional[str]:
  10. return self.args[0] if self.args else None
  11. class TemplateNotFound(IOError, LookupError, TemplateError):
  12. """Raised if a template does not exist.
  13. .. versionchanged:: 2.11
  14. If the given name is :class:`Undefined` and no message was
  15. provided, an :exc:`UndefinedError` is raised.
  16. """
  17. # Silence the Python warning about message being deprecated since
  18. # it's not valid here.
  19. message: t.Optional[str] = None
  20. def __init__(
  21. self,
  22. name: t.Optional[t.Union[str, "Undefined"]],
  23. message: t.Optional[str] = None,
  24. ) -> None:
  25. IOError.__init__(self, name)
  26. if message is None:
  27. from .runtime import Undefined
  28. if isinstance(name, Undefined):
  29. name._fail_with_undefined_error()
  30. message = name
  31. self.message = message
  32. self.name = name
  33. self.templates = [name]
  34. def __str__(self) -> str:
  35. return str(self.message)
  36. class TemplatesNotFound(TemplateNotFound):
  37. """Like :class:`TemplateNotFound` but raised if multiple templates
  38. are selected. This is a subclass of :class:`TemplateNotFound`
  39. exception, so just catching the base exception will catch both.
  40. .. versionchanged:: 2.11
  41. If a name in the list of names is :class:`Undefined`, a message
  42. about it being undefined is shown rather than the empty string.
  43. .. versionadded:: 2.2
  44. """
  45. def __init__(
  46. self,
  47. names: t.Sequence[t.Union[str, "Undefined"]] = (),
  48. message: t.Optional[str] = None,
  49. ) -> None:
  50. if message is None:
  51. from .runtime import Undefined
  52. parts = []
  53. for name in names:
  54. if isinstance(name, Undefined):
  55. parts.append(name._undefined_message)
  56. else:
  57. parts.append(name)
  58. parts_str = ", ".join(map(str, parts))
  59. message = f"none of the templates given were found: {parts_str}"
  60. super().__init__(names[-1] if names else None, message)
  61. self.templates = list(names)
  62. class TemplateSyntaxError(TemplateError):
  63. """Raised to tell the user that there is a problem with the template."""
  64. def __init__(
  65. self,
  66. message: str,
  67. lineno: int,
  68. name: t.Optional[str] = None,
  69. filename: t.Optional[str] = None,
  70. ) -> None:
  71. super().__init__(message)
  72. self.lineno = lineno
  73. self.name = name
  74. self.filename = filename
  75. self.source: t.Optional[str] = None
  76. # this is set to True if the debug.translate_syntax_error
  77. # function translated the syntax error into a new traceback
  78. self.translated = False
  79. def __str__(self) -> str:
  80. # for translated errors we only return the message
  81. if self.translated:
  82. return t.cast(str, self.message)
  83. # otherwise attach some stuff
  84. location = f"line {self.lineno}"
  85. name = self.filename or self.name
  86. if name:
  87. location = f'File "{name}", {location}'
  88. lines = [t.cast(str, self.message), " " + location]
  89. # if the source is set, add the line to the output
  90. if self.source is not None:
  91. try:
  92. line = self.source.splitlines()[self.lineno - 1]
  93. except IndexError:
  94. pass
  95. else:
  96. lines.append(" " + line.strip())
  97. return "\n".join(lines)
  98. def __reduce__(self): # type: ignore
  99. # https://bugs.python.org/issue1692335 Exceptions that take
  100. # multiple required arguments have problems with pickling.
  101. # Without this, raises TypeError: __init__() missing 1 required
  102. # positional argument: 'lineno'
  103. return self.__class__, (self.message, self.lineno, self.name, self.filename)
  104. class TemplateAssertionError(TemplateSyntaxError):
  105. """Like a template syntax error, but covers cases where something in the
  106. template caused an error at compile time that wasn't necessarily caused
  107. by a syntax error. However it's a direct subclass of
  108. :exc:`TemplateSyntaxError` and has the same attributes.
  109. """
  110. class TemplateRuntimeError(TemplateError):
  111. """A generic runtime error in the template engine. Under some situations
  112. Jinja may raise this exception.
  113. """
  114. class UndefinedError(TemplateRuntimeError):
  115. """Raised if a template tries to operate on :class:`Undefined`."""
  116. class SecurityError(TemplateRuntimeError):
  117. """Raised if a template tries to do something insecure if the
  118. sandbox is enabled.
  119. """
  120. class FilterArgumentError(TemplateRuntimeError):
  121. """This error is raised if a filter was called with inappropriate
  122. arguments
  123. """